'''
Created on Nov 25, 2012

@author: trananh
'''
from data.KTHDataReader import KTHDataReader
from collections import defaultdict
from trees.Forest import Forest
from trees.Tree import Tree
from evaluation.ConfMatrix import ConfMatrix
import random
import itertools as it


def topVote(votes, minvotes=0):
    # sort votes
    d = defaultdict(int)
    for l in votes:
        d[l] += 1
    ranked = [pair for pair in sorted(d.items(), key=lambda item: item[1], reverse=True)]
    return ranked[0][0] if ranked[0][1] >= minvotes else None


def getFeaturesDesc(featuresIdx, featureNames):
    desc = ''
    for i in range(len(featuresIdx)-1):
        desc += (featureNames[featuresIdx[i]] + ' + ')
    desc += featureNames[featuresIdx[-1]]
    return desc

if __name__ == '__main__':
    
    dataroot = '/Users/trananh/Workspace/Python/ua-gesture/data/KTH/'
    
    patterns_all = ['.*_d[1]_.*','.*_d[2]_.*','.*_d[3]_.*','.*_d[4]_.*', '.*_d[12]_.*','.*_d[13]_.*','.*_d[14]_.*','.*_d[23]_.*','.*_d[24]_.*','.*_d[34]_.*','.*_d[123]_.*','.*_d[124]_.*','.*_d[134]_.*','.*_d[234]_.*','.*_d[1234]_.*']
    patterns = ['.*_d[1]_.*','.*_d[14]_.*','.*_d[134]_.*','.*_d[1234]_.*']
    for testpattern in patterns:
        print '\n\n============================\n TEST PATTERN: ' + testpattern + '\n'
        for trainpattern in patterns_all:
            accuracies = []
            for i in range(3):
        
                datatype = 'ground-truth-2'
                
                # Load pose data
                #dataset = KTHDataReader.load(dataroot + datatype + '/pose-features-std')
                #dataset = KTHDataReader.load(dataroot + datatype + '/flow-features',dataset)
                #dataset = KTHDataReader.load(dataroot + datatype + '/flow-features-mag',dataset)
                #dataset = KTHDataReader.load(dataroot + datatype + '/flow-features-distr',dataset)
                
                # Save to pickle so we don't have to keep reading everytime
                #import pickle
                #datasetFile = dataroot + datatype + "/KTHdataset.pickle"
                #f = open(datasetFile, 'wb')
                #pickle.dump(dataset, f, pickle.HIGHEST_PROTOCOL)
                #f.close()
                
                
                # Load pickle and add to it
                import pickle
                datasetFile = dataroot + datatype + "/KTHdataset.pickle"
                f = open(datasetFile, 'rb')
                dataset = pickle.load(f)
                f.close()
                
                
                ## Split items into train and test set
                #items = dataset.getAllItems()
                #random.shuffle(items)
                #train = items[:int(len(items)*0.85)]
                #test = items[int(len(items)*0.85):]
                
                
                # Split train and test according to Schdult partition scheme
                # Train: 11, 12, 13, 14, 15, 16, 17, 18
                # Validation: 19, 20, 21, 23, 24, 25, 01, 04
                # Test: 22, 02, 03, 05, 06, 07, 08, 09, 10
                trainidx = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 1, 4]
                testidx = [22, 2, 3, 5, 6, 7, 8, 9, 10]
                train = dataset.getItemsByPersonIDs(trainidx)
                test = dataset.getItemsByPersonIDs(testidx)
                
                
                # Filter out some items
                import re
                for i in range(len(train)-1,-1,-1):
                    if re.match(trainpattern, train[i].attributes['segmentid']) is None:
                        del train[i]
                for i in range(len(test)-1,-1,-1):
                    if re.match(testpattern, test[i].attributes['segmentid']) is None:
                        del test[i]
                
                
                
                forest = Forest()
                
                # Train a random forest with N trees
                featureNames = train[0].attributes['featureNames']
                featuresIdx = [[x] for x in range(len(featureNames))]
                #featuresIdx.extend([list(x) for x in it.combinations(range(15),2)])
                #featuresIdx.extend([list(x) for x in it.combinations(range(15,len(featureNames)),2)])
                for i in featuresIdx:
                    #print 'Training tree: ' + getFeaturesDesc(i,featureNames)
                    random.shuffle(train)
                    tree = Tree(treeType=Tree.ENTROPY,name=getFeaturesDesc(i,featureNames),featuresIdx=i)
                    tree.addAll(train)
                    forest.add(tree)
            
                # Test random forest
                hits = 0; misses = 0
                for item in test:
                    votes = list()
                    for tree in forest.getTrees():
                        neighbors = tree.query(item, 5)
                        nominations = [i.label for i in neighbors]
                        
                        if len(nominations) <= 0:
                            #print 'No vote from ' + tree.name + ' for ' + item.attributes['segmentid']
                            continue
                        
                        pred = topVote(nominations, 3)
                        if pred is not None:
                            votes.extend(nominations)     
                        if pred is None and topVote(nominations) == item.label:
                            misses += 1
                        if pred is None and topVote(nominations) != item.label:
                            hits += 1
                    
                    item.prediction = topVote(votes)
                    
                # Compute statistics
                cmatrix = ConfMatrix.compute(test)
                #print ''
                #cmatrix.printSummary(probMode=True,latexMode=True)
                #cmatrix.printSummary(probMode=False,latexMode=True)
                #print '\nDone!'
                #print 'Correctly Ignored: ' + str(hits)
                #print 'Incorrectly Ignored: ' + str(misses)
            
                accuracies.append(cmatrix.accuracy())
        
            print '\n' + trainpattern + ': ' + str(accuracies) + ': ' + str(sum(accuracies)/len(accuracies))
    